package com.appkubes.fintech.restful.application.credit.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.appkubes.fintech.common.response.Response;
import com.appkubes.fintech.core.po.FintechCredit;
import com.appkubes.fintech.core.po.FintechCreditExample;
import com.appkubes.fintech.restful.application.credit.dao.CreditDao;
import com.appkubes.fintech.restful.application.credit.service.CreditService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @Author: Rongjie
 * @Date: 2020/01/05
 * @Description:
 */

@Service
@Slf4j
@Data
@Transactional
public class CreditServiceImpl implements CreditService {

    @Resource
    CreditDao creditDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private final static String REDIS_OPERATE_ORDER_LOCK_KEY_PREFIX = "kylin_fintech:operate_order_lock:";
    private final static String REDIS_OPERATE_RESTORE_LIMIT_LOCK_KEY_PREFIX = "kylin_fintech:operate_restore_limit_lock:";
    private final static String REDIS_OPERATE_DEDUCE_LIMIT_LOCK_KEY_PREFIX = "kylin_fintech:operate_credit_limit_lock:";


    /**
     * 获取用户信用额度
     *
     * @param userKey
     * @return
     */
    @Override
    public FintechCredit getCredit(String userKey) {
        FintechCredit credit = creditDao.selectByPrimaryKey(userKey);
        if (credit == null) {
            credit = new FintechCredit();
            credit.setUserKey(userKey);
            creditDao.insertSelective(credit);
            credit = creditDao.selectByPrimaryKey(userKey);//更新数据库默认值
        }
        return credit;
    }

    @Override
    public Response<FintechCredit> initCredit(String userKey, Integer amt) {
        return null;
    }

    @Override
    @Transactional
    public Response<FintechCredit> frozenCredit(String userKey, Integer amt) {
        FintechCredit credit = getByUserKey(userKey);
        if (credit.getForzenAmount() == null) {
            credit.setForzenAmount(0L);
        }
        Long surAmt = credit.getCreditAmount() - credit.getFreezeAmount() - credit.getForzenAmount();
        if (surAmt < amt) {
            return Response.fail("额度不足，冻结失败");
        }
        credit.setForzenAmount(credit.getForzenAmount() + amt);
        credit.setUpdateTime(new Date());
        creditDao.updateByPrimaryKey(credit);
        return Response.success(credit);
    }

    @Override
    @Transactional
    public Response<FintechCredit> unfrozenCredit(String userKey, Integer amt) {
        FintechCredit credit = getByUserKey(userKey);
        if (credit.getForzenAmount() == null) {
            credit.setForzenAmount(0L);
        }
        if (credit.getForzenAmount() < amt) {
            return Response.fail("解冻失败，额度不足");
        }
        credit.setForzenAmount(credit.getForzenAmount() - amt);
        credit.setUpdateTime(new Date());
        creditDao.updateByPrimaryKey(credit);
        return Response.success(credit);
    }

    @Override
    @Transactional
    public Response<FintechCredit> unOutfrozenCredit(String userKey, Integer amt) {
        FintechCredit credit = getByUserKey(userKey);
        if (credit.getForzenAmount() == null) {
            credit.setForzenAmount(0L);
        }
        if (credit.getForzenAmount() < amt) {
            return Response.fail("解冻失败，额度不足");
        }
        credit.setForzenAmount(credit.getForzenAmount() - amt); // 冻结金额减少
        credit.setFreezeAmount(credit.getFreezeAmount() + amt); // 已应金额增加
        credit.setUpdateTime(new Date());
        creditDao.updateByPrimaryKey(credit);
        return Response.success(credit);
    }

    @Override
    public Response<FintechCredit> recoverCredit(String userKey, Integer amt) {
//        FintechCredit credit=getByUserKey(userKey);
//        if(credit==null||amt==null){
//            return Response.fail("恢复失败");
//        }
//        if(credit.getFreezeAmount()==null){
//            credit.setFreezeAmount(0L);
//        }
//        credit.setFreezeAmount(credit.getFreezeAmount()-amt); // 减去使用过的
//       // credit.setCreditStatus(0);
//        credit.setUpdateTime(new Date());
//        creditDao.updateByPrimaryKey(credit);
        return Response.success();
    }

    private FintechCredit getByUserKey(String userKey) {
        FintechCreditExample example = new FintechCreditExample();
        example.createCriteria().andUserKeyEqualTo(userKey);
        List<FintechCredit> creditList = creditDao.selectByExample(example);
        if (creditList.size() <= 0) {
            return null;
        }
        return creditList.get(0);
    }

    @Override
    public Boolean isRefuseExpire(String userKey) {
        FintechCreditExample example = new FintechCreditExample();
        FintechCreditExample.Criteria criteria = example.createCriteria();
        criteria.andUserKeyEqualTo(userKey);
        criteria.andCreditStatusEqualTo(2);
        List<FintechCredit> list = creditDao.selectByExample(example);
        if (list.size() <= 0) {  //
            return true;
        }
        FintechCredit credit = list.get(0);
        if (DateUtil.between(credit.getUpdateTime(), new Date(), DateUnit.DAY) >= 30) { //30天失效
            return true;
        }
        return false;
    }

    @Override
    public Integer refuseExpireLeftDays(String userKey) {
        FintechCreditExample example = new FintechCreditExample();
        FintechCreditExample.Criteria criteria = example.createCriteria();
        criteria.andUserKeyEqualTo(userKey);
        criteria.andCreditStatusEqualTo(2);
        List<FintechCredit> list = creditDao.selectByExample(example);
        if (list.size() <= 0) {  //
            return -1;
        }
        FintechCredit credit = list.get(0);

        if (30 - (int) DateUtil.between(credit.getUpdateTime(), new Date(), DateUnit.DAY) >= 0) {
            return 30 - (int) DateUtil.between(credit.getUpdateTime(), new Date(), DateUnit.DAY);
        } else {
            return -1;
        }

    }
}
